package main

import (
	"fmt"
	"net/http"
	"os"

	"github.com/gin-gonic/gin"
)

// GET例子: 路由参数 查询字符串参数(缺省值)
// GET /get/:id/:name?x=1&y=s
// response string
func setGetAPI(r *gin.Engine) {
	// 路由参数:id :name
	r.GET("/get/:id/:name", func(c *gin.Context) {
		id := c.Params.ByName("id")
		name := c.Params.ByName("name")
		// 查询字符串参数 URL末尾的?x=?&y=?
		x := c.Query("x")
		// 查询字符串参数默认值
		y := c.DefaultQuery("y", "y")
		fmt.Printf("id %#v name %#v x %#v y %#v\n", id, name, x, y)
		// 返回字符串
		c.String(http.StatusOK, fmt.Sprintf("%v|%v|%v|%v", id, name, x, y))
	})
}

// POST例子: 路由参数 查询参数(缺省值) 表单参数(缺省值) 返回JSON
// POST /post/form/:id/:name?x=&y=y
// form-data formX formY
// response JSON
func setPostAPI(r *gin.Engine) {
	r.POST("/post/form/:id/:name", func(c *gin.Context) {
		id := c.Params.ByName("id")
		name := c.Params.ByName("name")
		x := c.Query("x")
		y := c.DefaultQuery("y", "y")
		formX := c.PostForm("formX")
		formY := c.DefaultPostForm("formY", "y")
		fmt.Printf("id %#v name %#v x %#v y %#v formX %#v formY %#v\n", id, name, x, y, formX, formY)
		c.JSON(http.StatusOK, gin.H{"id": id, "name": name, "x": x, "y": y, "formX": formX, "formY": formY})
	})
}

// PUT例子: 路由参数 查询参数(缺省值) 表单参数绑定到结构体 返回JSON
// PUT 127.0.0.1:8080/put/urlencoded/idValue/nameValue?x=&y=y
// urlencoded(处理似乎和form-data相同?) 表单绑定结构体 formX formY
// response JSON
func setPutAPI(r *gin.Engine) {
	r.PUT("/put/urlencoded/:id/:name", func(c *gin.Context) {
		id := c.Params.ByName("id")
		name := c.Params.ByName("name")
		x := c.Query("x")
		y := c.DefaultQuery("y", "y")
		type PutForm struct {
			// binding:"required" 不能缺失或为0值
			FormX int `form:"formX" binding:"required"`
			FormY int `form:"formY"`
		}
		var form PutForm
		// 在这种情况下，将自动选择合适的绑定
		if c.ShouldBind(&form) != nil {
			c.Status(http.StatusBadRequest)
			return
		}
		fmt.Printf("PutForm: %#v\n", form)
		c.JSON(http.StatusOK, gin.H{"id": id, "name": name, "x": x, "y": y,
			"formX": form.FormX, "formY": form.FormY})
	})
}

type PatchForm struct {
	// binding:"required" 不能缺失或为0值
	ID   int    `json:"id" form:"id" binding:"required"`
	Name string `json:"name" form:"name" binding:"required"`
}

// PUT例子: JSON参数绑定到结构体 返回JSON
// PATCH 127.0.0.1:8080/patch
// JSON id name
// response JSON
func setPatchAPI(r *gin.Engine) {
	r.PATCH("/patch", func(c *gin.Context) {
		var form PatchForm
		// 在这种情况下，将自动选择合适的绑定
		if err := c.ShouldBind(&form); err != nil {
			fmt.Fprintf(os.Stderr, "%#v\n", form)
			fmt.Fprintln(os.Stderr, err.Error())
			c.Status(http.StatusBadRequest)
			return
		}
		fmt.Printf("PatchForm: %#v\n", form)
		c.JSON(http.StatusOK, gin.H{"id": form.ID, "name": form.Name})
	})
}

// PUT例子: 查询参数绑定到结构体 返回JSON
// DELETE /delete?id=&name=
// response string
func setDeleteAPI(r *gin.Engine) {
	r.DELETE("/delete", func(c *gin.Context) {
		var form PatchForm
		if c.ShouldBindQuery(&form) != nil {
			c.Status(http.StatusBadRequest)
			return
		}
		fmt.Printf("form %#v\n", form)
		c.JSON(http.StatusOK, gin.H{"id": form.ID, "name": form.Name})
	})
}

func setupRouter() *gin.Engine {
	// Disable Console Color
	// gin.DisableConsoleColor()
	r := gin.Default()

	setGetAPI(r)
	setPostAPI(r)
	setPutAPI(r)
	setPatchAPI(r)
	setDeleteAPI(r)
	return r
}

func main() {
	r := setupRouter()

	// Listen and Server in 127.0.0.1:8080 localhost:8080
	r.Run(":8080")
}
